package org.ace.logic.user.impl;

import java.util.List;

import javax.annotation.Resource;

import io.netty.channel.Channel;

import org.ace.account.IAccountBiz;
import org.ace.biz.user.IPlayerBiz;
import org.ace.constans.PlayerEventConstans;
import org.ace.dao.model.Player;
import org.ace.endingCode.SocketModel;
import org.ace.event.model.PlayerEvent;
import org.ace.logic.IHandlerServ;
import org.ace.logic.user.AbstractUserHandlerImpl;
import org.ace.logic.user.dto.CreatePlayerDTO;
import org.ace.logic.user.dto.PlayerDTO;
import org.ace.logic.user.protocol.PlayerProtocol;
import org.ace.tool.IExecutorPool;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;

public class PlayerHandlerServImpl extends AbstractUserHandlerImpl implements
		IHandlerServ ,ApplicationListener<PlayerEvent>{

	//玩家角色实现类 继承ApplicationListener<PlayerEvent> 实现对hp exp属性变更事件的监听
		@Resource(name="playerBiz")
		private IPlayerBiz playerBiz;
		@Resource(name="accountBiz")
		private IAccountBiz accountBiz;
		@Resource(name="executorPool")
		private IExecutorPool executorPool;
			
		@Override
		public void Colse(final Channel channel) {
			executorPool.execute(new Runnable() {
				
				@Override
				public void run() {
					playerBiz.offLine(channel);			
				}
			});	
		}
		
		@Override
		protected void process(Channel channel, SocketModel message) {
			switch(message.getCommand())
			{
			case  PlayerProtocol.GET_LIST_CREQ:
				getList(channel);
				break;
			case PlayerProtocol.CREATE_CREQ:
				create(channel,message);
				break;
			case PlayerProtocol.SELECT_CREQ:
				enter(channel,message);
			}

		}

		private void enter(final Channel channel,SocketModel<Integer> message) {
			final Integer accId = accountBiz.getAccId(channel);
			final Integer playerId = message.getMessage();
			//不管是创建还是 选择角色进入地图,都需要修改地图，会造成数据竞争，
			//放在单线程里面,显然很好管理，不用去加锁解决数据竞争的问题，用多线程效率也和这个差不多I的
			executorPool.execute(new Runnable(){

				@Override
				public void run() {
					if(playerBiz.select(playerId, channel, accId))
					{//Player是实体数据模型，用来存储 修改数据
						//这个账号 和 角色合法 返回角色 消息模型，客户端进入游戏
						Player player = playerBiz.get(playerId);//发送的是PlayerDTO消息模型
						write(channel, PlayerProtocol.SELECT_SRES,new PlayerDTO(player));
					}
					else
					{
						//不存在这个角色，返回  null 表示,没有这个角色
						write(channel ,PlayerProtocol.SELECT_SRES, null);
					}
				}
				
			});
		}


	    /*
	     * 创建角色 ，这里客户端发送来的消息模型 是CreatePlayerDTO
	     * */
		private void create(final Channel channel,SocketModel<CreatePlayerDTO> message) 
		{
			final Integer accId = accountBiz.getAccId(channel);
			CreatePlayerDTO dto =message.getMessage();
			final int job =dto.job;
			final String name= dto.name;
			executorPool.execute(new Runnable(){
	       
				@Override
				public void run() {
					write(channel,PlayerProtocol.CREATE_SRES , playerBiz.create(job, name, accId));		
				}			
			});
		}

		private void getList(Channel channel) {
			Integer accId = accountBiz.getAccId(channel);
		
			if(accId.equals(-1))
			{// 安全性检查 ，账号上线缓存里没有 账号
				write(channel , PlayerProtocol.GET_LIST_SRES ,null);
				return;
			}
			List<Player> players = playerBiz.getList(accId);
			//想了想，其实这里传整个玩家的数据也是可以的，到时候客户端存储起来
			PlayerDTO[] dtos=new PlayerDTO[players.size()];
			for(int i=0;i<dtos.length;i++)
			{
				dtos[i] =new PlayerDTO(players.get(i));
			}
			write(channel ,PlayerProtocol.GET_LIST_SRES,dtos);
		}

		@Override
		public void onApplicationEvent(PlayerEvent arg0) {
			switch(arg0.getType())
			{
			case PlayerEventConstans.LEVEL_UP:
				write(arg0.getUserId(),PlayerProtocol.LEVEL_UP_SRES,arg0.getValue());
				break;
			case PlayerEventConstans.HP_CHANGE:
				write(arg0.getUserId(),PlayerProtocol.HP_CHANGE_SRES,arg0.getValue());
			}	
		}

}
